package web

import (
	"html/template"
	"log"
	"net/http"
	"os"

	"gitee.com/dayu1985/framework/logging"

	"strings"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/render"
	rice "github.com/giter/go.rice"
)

type HTMLDebug struct {
	Files []string
}

func (r HTMLDebug) Instance(name string, data interface{}) render.Render {

	return render.HTML{
		Template: r.loadTemplate(),
		Name:     name,
		Data:     data,
	}
}

func (r HTMLDebug) loadTemplate() *template.Template {

	if len(r.Files) > 0 {

		tpl, err := template.New("-").Parse("-")

		if err != nil {
			return nil
		}

		tpl.Funcs(FuncMap())

		tpl, err = tpl.ParseFiles(r.Files...)

		if err != nil {
			return nil
		}

		return tpl
	}

	panic("the HTML debug render was created without files or glob pattern")

}

func parse(tpl *template.Template, path string, content string) {

	if _, err := tpl.New(path).Funcs(FuncMap()).Parse(content); err != nil {
		logging.Error("Error parsing ", path, err)
	} else {
		log.Printf("parsed %s", path)
	}
}

//GinTemplatesWithGoRice Gin TEMPLATES WITH Go.rice
func GinTemplatesWithGoRice(r *gin.Engine, box *rice.Box, suffix ...string) {

	if box.IsAppended() {
		logging.Info("Using appended box [%s]...", box.Name())
	} else if box.IsEmbedded() {
		logging.Info("Using embedded box [%s]...", box.Name())
	} else {
		logging.Info("Using directory [./%s]", box.Name())
	}

	dirMode := !box.IsAppended() && !box.IsEmbedded()

	tpl, err := template.New("-").Parse("-")

	if err != nil {
		panic(err) // Unreachable!
	}

	files := []string{}

	box.Walk("/", func(path string, info os.FileInfo, err error) error {

		logging.Info("Listing %s...", path)

		if err != nil {
			panic(err)
		}

		for _, s := range suffix {

			if strings.HasSuffix(path, s) {

				path = strings.TrimPrefix(path, "/")

				if !dirMode {

					v, err := box.String(path)

					if err != nil {
						log.Println("Error on reading file " + path)
						continue
					}

					parse(tpl, path, v)

				} else {
					files = append(files, box.Name()+"/"+path)
				}
			}
		}

		return nil
	})

	if dirMode {
		r.HTMLRender = HTMLDebug{Files: files}
	} else {
		r.SetHTMLTemplate(tpl)
	}
}

//GinStaticHandlerWithGoRice Gin Static Handler with Go.Rice
func GinStaticHandlerWithGoRice(box *rice.Box) func(c *gin.Context) {

	fileServer := http.StripPrefix("/", http.FileServer(box.HTTPBox()))

	return func(c *gin.Context) {

		if c.Request.Method != http.MethodGet && c.Request.Method != http.MethodHead {
			return
		}

		url := c.Request.URL.Path
		file := strings.TrimPrefix(url, "/")

		if strings.LastIndex(file, "/") >= strings.LastIndex(file, ".") {
			return // so this means a folder, not a regular file
		}

		if f, _ := box.Open(file); f != nil {
			f.Close()
			fileServer.ServeHTTP(c.Writer, c.Request)
		}
	}
}

//GinStaticHandlerWithLocalFileSystem Gin Static Handler with Local FileSystem
//@param box 根结点
//@param root 根目录
//@param prefixes 真实路径前缀
func GinStaticHandlerWithLocalFileSystemAndGoRice(box *rice.Box, root string, prefixes ...string) func(c *gin.Context) {

	riceServer := http.StripPrefix("/", http.FileServer(box.HTTPBox()))

	fs := gin.Dir(root, false)
	fileServer := http.StripPrefix("/", http.FileServer(fs))

	if len(prefixes) == 0 {
		prefixes = []string{""}
	}

	return func(c *gin.Context) {

		if c.Request.Method != http.MethodGet && c.Request.Method != http.MethodHead {
			return
		}

		url := c.Request.URL.Path

		for _, prefix := range prefixes {

			file := url

			if prefix != "" {
				file = prefix + "/" + file
			}

			file = strings.TrimPrefix(strings.Replace(file, "//", "/", -1), "/")

			if strings.LastIndex(file, "/") >= strings.LastIndex(file, ".") {
				return // so this means a folder, not a regular file
			}

			if f, _ := box.Open(file); f != nil {
				f.Close()
				c.Request.URL.Path = "/" + file
				riceServer.ServeHTTP(c.Writer, c.Request)
				return
			}

			if f, _ := fs.Open(file); f != nil {
				f.Close()
				c.Request.URL.Path = "/" + file
				fileServer.ServeHTTP(c.Writer, c.Request)
				return
			}
		}
	}
}
